home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MACSHELL / MS1 / SHELL_SO / PROC.C < prev    next >
Text File  |  1992-12-02  |  20KB  |  814 lines

  1. /*
  2.  *    MacShell Source File
  3.  *
  4.  *    Copyright (c) 1989, 1990, 1991, 1992  Suick Bay Technologies.  All rights reserved.
  5.  *
  6.  *
  7.  *    RESTRICTIONS ON MacShell program and source code.
  8.  *
  9.  *    Ñ╩MacShell¬ is a product of Suick Bay Technologies and is provided for
  10.  *    restricted use by the owner of the CDROM "Disk to the future II".
  11.  *
  12.  *    Ñ╩No permission is granted for any commercial use without the written
  13.  *    consent of the Suick Bay Technologies.
  14.  *
  15.  *    Ñ╩No permission is granted for any redistribution of any kind use without
  16.  *    the written consent of the Suick Bay Technologies.
  17.  *
  18.  *    Ñ╩Permission is granted to use this for any personal noncommercial use.
  19.  *
  20.  *    Ñ╩You may not distribute source or executable code at all, nor may you 
  21.  *    distribute it with or within a commercial product without the written
  22.  *    consent of the Suick Bay Technologies.  Please send modifications to 
  23.  *    the author for inclusion in updates to the program.  Thanks.
  24.  *
  25.  *
  26.  *    MacShell¬ IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  27.  *    WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  28.  *    PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  29.  *
  30.  *    SUICK BAY TECHNOLOGIES SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  31.  *    INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY MACSHELL
  32.  *    OR ANY PART THEREOF. 
  33.  *
  34.  *    In no event will Suick Bay Technologies be liable for any lost revenue
  35.  *    or profits or other special, indirect and consequential damages, even if
  36.  *    Suick Bay Technologies has been advised of the possibility of such damages.
  37.  *
  38.  *    Suick Bay Technologies can be reached at:
  39.  *    
  40.  *    8768 Cottonwood lane
  41.  *    Maple Grove, MN 55369
  42.  *    Voice: (612) 425-7025
  43.  *    AppleLink: D5233
  44.  *    
  45.  *
  46.  *    No parts of this software may be reproduced or stored in a
  47.  *    retrieval system or transmitted in any form, or any means,
  48.  *    electronic, mechanical, photocopying, recording or otherwise,
  49.  *    without the prior written permission of Suick Bay Technologies.
  50.  *    
  51.  *    Spread the word and not the disk.
  52.  *    
  53.  *    SPK 012290    :    Initial
  54.  */
  55.  
  56. #include    "System.h"
  57. #include    "Parse.h"
  58. #include    "Proc.h"
  59. #include    "Path.h"
  60. #include    "Shell.h"
  61. #include    "Struct.h"
  62.  
  63. /*******************************************************************
  64.  *    UTIL FUNCTIONS    
  65.  *******************************************************************/
  66.  
  67. #define    ValidProc(X) ((X)>=0&&(X)<MAX_PROCS&&(**MyShell).Proc[(X)].ProcActive)
  68.  
  69. GetArgv( WHandle ShellWh, int ProcID, int16 Arg, char *buf )
  70. {
  71. char    *cp;
  72. int16        index;
  73. ShellWindRec    **MyShell;
  74.  
  75.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  76.  
  77.     index = (**MyShell).Proc[ ProcID ].argv[ Arg ];
  78.     cp = &((**MyShell).Proc[ ProcID ].cmdline[ index ]);
  79.  
  80.     while( *buf++ = *cp++ );
  81. }
  82.  
  83. /*******************************************************************
  84.  *    STANDARD INTERFACE FUNCTIONS    
  85.  *******************************************************************/
  86.  
  87. CommandString( char *string, WHandle ShellWh )
  88. {
  89. ProcPtr    p;
  90. ShellWindRec    **MyShell;
  91. PEHandle        hPE;
  92. int32            len;
  93. char            *sp;
  94.  
  95.     if( ShellWh == NULL )
  96.         return;
  97.  
  98.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  99.  
  100. /*
  101.  *    Send string to the input PE
  102.  */
  103.     hPE = (**MyShell).ihPE;
  104.     PESetSelect( (**hPE).selEnd, (**hPE).selEnd, hPE );
  105.     sp = string;
  106.  
  107.     while( *sp )    /* convert newlines to crs */
  108.         {
  109.         if( *sp == '\n' )
  110.             *sp = '\r';
  111.         sp++;
  112.         }
  113.  
  114.     len = (int32) strlen( string );
  115.     PEInsert( string, len, hPE ); 
  116.     AdjustInput( ShellWh, TRUE );
  117. }
  118.  
  119. /*******************************************************************/
  120.  
  121. WriteToStdOut( char *string, WHandle ShellWh )
  122. {
  123. ProcPtr    p;
  124. ShellWindRec    **MyShell;
  125.  
  126.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  127.  
  128.     p = (**MyShell).Proc[ STDOUT_PROCID ].CmdProcPtr;
  129.  
  130.     if( p && ValidProc( STDOUT_PROCID ) )
  131.         (*p)( PROC_STDIN, ShellWh, STDOUT_PROCID, string );
  132. }
  133.     
  134. /*******************************************************************/
  135.  
  136. Boolean            SendToken( WHandle ShellWh, int ProcID, int token )
  137. {
  138. ProcPtr            p;
  139. ShellWindRec    **MyShell = (ShellWindRec **) (**ShellWh).thing;
  140.  
  141.     if( ValidProc( ProcID ) )
  142.         {
  143.         p = (**MyShell).Proc[ ProcID ].CmdProcPtr;
  144. #ifdef    PROCDEBUG
  145.         printf( "Sending Token %d to %d\n", token, ProcID );    
  146. #endif
  147.         if( p && ValidProc( ProcID ) )
  148.             return( (*p)( token, ShellWh, ProcID, NULL ) );
  149.         }
  150.     else
  151.         return( FALSE );
  152. }
  153.  
  154. /*******************************************************************/
  155.  
  156. Boolean        SendBreakToken(  WHandle ShellWh  )
  157. {
  158. ShellWindRec    **MyShell = (ShellWindRec **) (**ShellWh).thing;
  159.     return( SendToken( ShellWh, STDIN_PROCID, PROC_BREAK ) );
  160. }
  161.  
  162. /*******************************************************************/
  163.  
  164. Boolean            SendOutToken( WHandle ShellWh, int ProcID, int token )
  165. {
  166. ProcPtr            p;
  167. int                OutProcID;
  168. ShellWindRec    **MyShell;
  169.  
  170.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  171.         
  172.     if( ValidProc( ProcID ) )
  173.         {
  174.         OutProcID = (**MyShell).Proc[ ProcID ].StdOutProcID;
  175.         p = (**MyShell).Proc[ OutProcID ].CmdProcPtr;
  176.  
  177. #ifdef    PROCDEBUG
  178.         printf( "Sending STDOUT TOKEN  %d from %d to %d\n",
  179.             token, ProcID, OutProcID );
  180. #endif
  181.         if( p && ValidProc( OutProcID ) )
  182.             return( (*p)( token, ShellWh, OutProcID, NULL ) );
  183.         }
  184.     else
  185.         return( FALSE );
  186. }
  187.  
  188. /*******************************************************************/
  189.  
  190. StdOut( WHandle ShellWh, int ProcID, char *string )
  191. {
  192. ProcPtr            p;
  193. int                OutProcID;
  194. ShellWindRec    **MyShell;
  195.  
  196.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  197.  
  198.     if( ValidProc( ProcID ) )
  199.         {
  200.         OutProcID = (**MyShell).Proc[ ProcID ].StdOutProcID;
  201.         p = (**MyShell).Proc[ OutProcID ].CmdProcPtr;
  202.  
  203.         if( p && ValidProc( OutProcID ) )
  204.             (*p)( PROC_STDIN, ShellWh, OutProcID, string );
  205.         }
  206. }
  207.  
  208. /*******************************************************************/
  209.  
  210. StdErr( WHandle ShellWh, int ProcID, char *string )
  211. {
  212. ProcPtr            p;
  213. int                ErrProcID;
  214. ShellWindRec    **MyShell;
  215.  
  216.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  217.  
  218.     if( ValidProc( ProcID ) )
  219.         {
  220.         ErrProcID = (**MyShell).Proc[ ProcID ].StdErrProcID;
  221.         p = (**MyShell).Proc[ ErrProcID ].CmdProcPtr;
  222.     
  223.         if( p && ValidProc( ErrProcID ) )
  224.             (*p)( PROC_STDIN, ShellWh, ErrProcID, string );
  225.         }
  226. }
  227.  
  228. /*******************************************************************
  229.  *    SHELL INTERFACE FUNCTIONS    
  230.  *
  231.  *    This function write to the shell for stdout and strerr
  232.  *******************************************************************/
  233.  
  234. ShellOutProc( int ProcToken, WHandle ShellWh, int ProcID, char *string )
  235. {
  236. char    *cp;
  237. ShellWindRec    **MyShell;
  238.  
  239.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  240.  
  241.     if( ProcToken == PROC_STDIN && ShellWh && string )
  242.         {
  243.         cp = string;
  244.         while( *cp )        /* convert newlines to <cr> */
  245.             {
  246.             if( *cp == '\n' )
  247.                 *cp = '\r';
  248.             cp++;
  249.             }
  250.             
  251.         ShellAddStr( string, ShellWh );
  252.         }
  253.     else if( ProcToken == PROC_BREAK )
  254.         {
  255.         /* rewrire stdin and stdout to the shell proc */
  256.         if( ProcID != STDOUT_PROCID )
  257.             (**MyShell).Proc[ ProcID ].ProcActive = FALSE;
  258.         else
  259.             ResetStdIO( ShellWh );
  260.         }
  261. }
  262.  
  263. /*******************************************************************/
  264.  
  265. InitProc( WHandle ShellWh, int ProcID, int inStream, int outStream, int errStream )
  266. {
  267. int    i;
  268. ShellWindRec    **MyShell;
  269.  
  270.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  271.     (**MyShell).Proc[ ProcID ].ProcActive = TRUE;
  272. /*
  273.  *    Connect the streams
  274.  */
  275.      (**MyShell).Proc[ inStream ].StdOutProcID = ProcID;
  276.      (**MyShell).Proc[ ProcID ].StdOutProcID = outStream;
  277.      (**MyShell).Proc[ ProcID ].StdErrProcID = errStream;
  278.      
  279.     SendToken( ShellWh, ProcID, PROC_INIT );
  280. }
  281.  
  282. /*******************************************************************/
  283.  
  284. /*
  285.  *    Find an inactive proc slot and return it.
  286.  *    If no slot is availible then return UNKNOWN
  287.  */
  288.  
  289. int        GetProcSlot( WHandle ShellWh )
  290. {
  291. int        proc;
  292. ShellWindRec    **MyShell;
  293.  
  294.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  295.  
  296.     for( proc = 0; proc < MAX_PROCS; proc++ )
  297.         if( (**MyShell).Proc[ proc ].ProcActive == FALSE )
  298.             return( proc );
  299.  
  300.     return( UNKNOWN );
  301. }
  302.  
  303. /********************************************************************
  304.  *    Command line scanner
  305.  ********************************************************************/
  306.  
  307. CLScanner( int ProcToken, WHandle ShellWh, int ProcID, char *string )
  308. {
  309. char        *cp, **ch, buf[ 64 ],
  310.             stdInFile[ 64 ],
  311.             stdOutFile[ 64 ];
  312. int16        currProcSlot, lastProcSlot,
  313.             pipeFromLast, pipeToNext, pipeErr,
  314.             i, ioOk, cmdc, tokenType, lastToken,
  315.             ProcDataAvail, parseErr = 0,
  316.             inProc, outProc, errProc;
  317.             
  318. ShellWindRec    **MyShell;
  319. /*
  320.  *    Command execution vars
  321.  */
  322. ProcPtr        theCommand;
  323. int            needsStdIn;
  324.  
  325.     (**ShellWh).entryCnt++;
  326.  
  327.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  328.  
  329.     lastProcSlot = CL_PROCID;
  330.     if( ProcToken == PROC_STDIN && ShellWh && string )
  331.         {
  332.         ExpandShellStr( ShellWh, string );
  333.         cp = string;
  334.         
  335.         currProcSlot = GetProcSlot( ShellWh );
  336.         if( currProcSlot == UNKNOWN )
  337.             {
  338.             ShellError( se_noProcSlots );    
  339.             return;
  340.             }
  341.         else    /* Initialize the Proc */
  342.             {
  343.             (**MyShell).Proc[ currProcSlot ].argc         = 0;
  344.             cmdc = 0;
  345.             
  346.             (**MyShell).StdOutAppend     = FALSE;
  347.             stdInFile[ 0 ]     = '\0';
  348.             stdOutFile[ 0 ]    = '\0';
  349.             lastToken         = UNKNOWN;
  350.             ProcDataAvail     = FALSE;
  351.             lastProcSlot     = CL_PROCID;
  352.             pipeFromLast     = FALSE;
  353.             pipeToNext         = FALSE;
  354.             pipeErr            = FALSE;
  355.             ioOk            = FALSE;
  356.             }
  357.  
  358.         inProc     = STDIN_PROCID;
  359.         outProc = STDOUT_PROCID;
  360.         errProc = STDERR_PROCID;
  361.         
  362.         while( cp )
  363.             {
  364.             cp = GetShellToken( cp, buf, &tokenType );
  365.             parseErr = 0;
  366.                     
  367. #ifdef    PROCDEBUG
  368.             printf( "Token : '%s' = %d\n", buf, tokenType );
  369. #endif            
  370.             switch( tokenType )
  371.                 {
  372.                 case    tkn_andf        :    /* '&&'            */
  373.                 case    tkn_orf            :    /* '||'            */
  374.                 case    tkn_background    :    /* '&'            */
  375.                     break;
  376.  
  377.                 case    tkn_pipeOutErr    :    /* '|&'            */
  378.                     pipeErr = TRUE;
  379.                 case    tkn_pipe        :    /* '|'            */
  380.                     pipeToNext = TRUE;
  381.                 
  382.                 case    tkn_separator    :    /* ';'            */
  383.                 case    tkn_eol            :    
  384. Execute:
  385.                      if( tokenType == tkn_eol )
  386.                         procPrintf( ShellWh, ProcID, 
  387.                             "%s%s", GetPromptStr( ShellWh ), string );
  388.                         
  389.                     if( ProcDataAvail ) /* Start the process */
  390.                         {
  391.                         char    command[ 256 ];
  392.                         
  393.                         GetArgv( ShellWh, currProcSlot, 0, command );
  394.  
  395.                          if( GetCommandInfo( command, &theCommand, &needsStdIn ) )
  396.                              {
  397. forceCommand :
  398.                             /* save the command */
  399.                             RecordCmd( string, ShellWh );
  400.                             
  401.                              (**MyShell).Proc[ currProcSlot ].CmdProcPtr = theCommand;
  402.          
  403.                             if( *stdInFile && needsStdIn )    /* init stdin */
  404.                                  {
  405.                                 ProcPtr    p;
  406.                                 p = (**MyShell).Proc[ STDIN_PROCID ].CmdProcPtr;
  407.                                 if( p )
  408.                                     ioOk = (*p)( PROC_INIT, ShellWh, STDIN_PROCID, stdInFile );
  409.                                     
  410.                                 if( ioOk == FALSE )
  411.                                     parseErr = se_ioRedir;
  412.                                 }
  413.                             if( *stdOutFile )    /* init stdout */
  414.                                  {
  415.                                 ProcPtr    p;
  416.                                 p = (**MyShell).Proc[ STDOUT_PROCID ].CmdProcPtr;
  417.                                 if( p )
  418.                                     ioOk = (*p)( PROC_INIT, ShellWh, STDOUT_PROCID, stdOutFile );
  419.                                     
  420.                                 if( ioOk == FALSE )
  421.                                     parseErr = se_ioRedir;
  422.                                 }
  423.     
  424.                             if( pipeFromLast && (lastProcSlot != CL_PROCID))
  425.                                 InitProc( ShellWh, currProcSlot, lastProcSlot, outProc, errProc );
  426.                             else
  427.                                 {
  428.                                 InitProc( ShellWh, currProcSlot, inProc, outProc, errProc );
  429.                                 
  430.                                 if( needsStdIn && (parseErr == noErr))
  431.                                     {
  432.                                     (**MyShell).prompt = 1;
  433.                                     }
  434.                                 }
  435.                                 
  436.                             if( tokenType == tkn_separator )
  437.                                 {
  438.                                 /* command was separated on the command line
  439.                                    run the command until it is complete */
  440.                                 
  441.                                 while( (**MyShell).Proc[ currProcSlot ].ProcActive )
  442.                                        ProcMgrIdle( ShellWh );
  443.  
  444.                                 outProc = (**MyShell).Proc[ ProcID ].StdOutProcID;
  445.                                 errProc = (**MyShell).Proc[ ProcID ].StdErrProcID;
  446.                                 }
  447.                             
  448.                             /* Set up another proc slot */
  449.                             lastProcSlot = currProcSlot;
  450.                             ProcDataAvail = FALSE;
  451.                             pipeFromLast = pipeToNext;
  452.                             
  453.                             currProcSlot = GetProcSlot( ShellWh );
  454.                             if( currProcSlot == UNKNOWN )
  455.                                 {
  456.                                 ShellError( se_noProcSlots );    
  457.                                 return;
  458.                                 }
  459.                             else    /* Initialize the Proc */
  460.                                 {
  461.                                 (**MyShell).Proc[ currProcSlot ].argc = 0;
  462.                                 cmdc             = 0;
  463.                                 
  464.                                 stdInFile[ 0 ]     = '\0';
  465.                                 stdOutFile[ 0 ]    = '\0';
  466.                                 ProcDataAvail    = FALSE;
  467.                                 (**MyShell).StdOutAppend     = FALSE;
  468.                                 
  469.                                 if( tokenType == tkn_separator )
  470.                                     {
  471.                                     lastProcSlot     = CL_PROCID;
  472.                                     pipeToNext        = FALSE;
  473.                                     pipeFromLast    = FALSE;
  474.                                     pipeErr         = FALSE;
  475.                                     }
  476.                                 }
  477.                             }
  478.                         else if( BuiltInCMD( ShellWh, currProcSlot, ProcID, command ))
  479.                             {
  480.                             RecordCmd( command, ShellWh );
  481.                             }                            
  482.                         else    /* name could be a script or an application */
  483.                             {
  484.                             int        refNum;
  485.                             char    str[ 256 ];
  486.                             
  487.                             refNum = OpenFile( ShellWh, command, 'TEXT', fsRdPerm );
  488.                             
  489.                             if( !refNum )
  490.                                 {
  491.                                 strcpy( str, command );
  492.                                 strcat( str, ".script" );    
  493.                                 refNum = OpenFile( ShellWh, str, 'TEXT', fsRdPerm );
  494.                                 if( refNum )
  495.                                     strcpy( command, str );
  496.                                 }
  497.                             
  498.                             if( refNum )
  499.                                 {
  500.                                 int        ni, na, nc = 0;
  501.                                 char    *cp, *np;
  502.                                 
  503.                                 FSClose( refNum );
  504.                                 
  505.                                 /* save the new command and arguments */
  506.                                 na = (**MyShell).Proc[ currProcSlot ].argc;
  507.                                 
  508.                                 /* copy command line to new script proc */
  509.                                 (**MyShell).Proc[ currProcSlot ].argv[ 0 ] = 0;
  510.                                 
  511.                                 cp = command;
  512.                                 while( *cp++ )
  513.                                     nc++;
  514.                                 nc++;
  515.                                 
  516.                                 /* copy argvs to new script proc */
  517.                                 for( ni = 1; ni < na; ni++ )
  518.                                     {
  519.                                     GetArgv( ShellWh, currProcSlot, ni, str );
  520.                                     
  521.                                     (**MyShell).Proc[currProcSlot].argv[ni] = nc;
  522.                                     
  523.                                     np = str;
  524.                                     while( *cp++ = *np++ )
  525.                                         nc++;
  526.                                     nc++;
  527.                                     }
  528.                                 
  529.                                 for( ni = 0; ni < nc; ni++ )
  530.                                     (**MyShell).Proc[ currProcSlot ].cmdline[ni] = command[ni];
  531.                                 
  532.                                 theCommand = (ProcPtr) DoSCRIPT;
  533.                                 needsStdIn = FALSE;
  534.                                 goto forceCommand;
  535.                                 }
  536.                             else
  537.                                 {
  538.                                 refNum = OpenFile( ShellWh, command, 'APPL', fsRdPerm );
  539.                             
  540.                                 if( refNum )
  541.                                     {
  542.                                     pathType    pt;
  543.                                     OsErr        lerr;
  544.                                     
  545.                                     FSClose( refNum );
  546.                                     /* application */
  547.                                     
  548.                                     if( CanLaunch() == FALSE )
  549.                                         {
  550.                                         procPrintf( ShellWh, ProcID,
  551.                                             "sh : Applications can only be launched under MultiFinder\n" );
  552.                                         }
  553.                                     else
  554.                                         {
  555.                                         pt = SetCurrPath( command );
  556.                                         if( pt == pathIsFile )
  557.                                             {
  558.                                             int        cv;
  559.                                             long    cd, cp;
  560.                                             
  561.                                             GetPWDInfo( &cv, &cd, &cp );
  562.                                             strcpy( str, GetLastScan() );
  563.                                             RecordCmd( str, ShellWh );
  564.                                             CtoPstr( str );
  565.                                             
  566.                                             lerr = DoLaunch( str, cv, cd );
  567.                                             
  568.                                             if( lerr )
  569.                                                 procPrintf( ShellWh, ProcID,
  570.                                                     "sh : can't launch %ps (%d)\n", str, lerr );
  571.                                                     
  572.                                             }
  573.                                         }
  574.                                         
  575.                                     ResetShellPWD( ShellWh );
  576.                                     }
  577.                                 else
  578.                                     parseErr = se_unknownCmd;
  579.                                 }
  580.                             }
  581.                         }
  582.                     break;
  583.  
  584.                 case    tkn_var            :    /* '$'            */
  585.                 case    tkn_identifier    :    /*                 */
  586.                 case    tkn_digit        :    /* '0-9.'        */
  587.                     {
  588.                     char    *s;
  589.                     char    varName[ 64 ];
  590.                     /* save as argument */
  591.                     
  592.                     if( tokenType == tkn_var )
  593.                         {                        
  594.                         if( cp )
  595.                             {
  596.                             cp = GetShellToken( cp, varName, &tokenType );
  597.                             s = ShellGetVar( ShellWh, varName );
  598.                             }
  599.                         else
  600.                             s = buf;
  601.                         }
  602.                     else
  603.                         s = buf;
  604.                         
  605.                     (**MyShell).Proc[currProcSlot].argv[
  606.                         (**MyShell).Proc[currProcSlot].argc] = cmdc;
  607.             
  608.                     while ( (**MyShell).Proc[ currProcSlot ].cmdline[ cmdc++ ] = *s++ );
  609.                     (**MyShell).Proc[ currProcSlot ].argc++;
  610.                     ProcDataAvail = TRUE;
  611.                     }
  612.                     break;
  613.  
  614.                 case    tkn_inputRedirect:    /* '<'            */
  615.                     if( cp )
  616.                         {
  617.                         cp = GetShellToken( cp, stdInFile, &tokenType );
  618.                         if( tokenType != tkn_identifier )
  619.                             parseErr = se_expectFile;
  620.                         }
  621.                     else
  622.                         parseErr = se_expectFile;
  623.                     break;
  624.                                     
  625.                 case    tkn_outputAppend:    /* '>>'            */
  626.                     (**MyShell).StdOutAppend = TRUE;
  627.                     
  628.                 case    tkn_outputRedirect:    /* '>'            */
  629.                     if( cp )
  630.                         {
  631.                         cp = GetShellToken( cp, stdOutFile, &tokenType );
  632.                         if( tokenType != tkn_identifier )
  633.                             parseErr = se_expectFile;
  634.                         }
  635.                     else
  636.                         parseErr = se_expectFile;
  637.                     break;
  638.                                         
  639.                 case    tkn_comment        :    /* '#'            */
  640.                     while( cp )
  641.                         {
  642.                         cp = GetShellToken( cp, stdOutFile, &tokenType );
  643.                         if( tokenType == tkn_eol )
  644.                             break;
  645.                         }
  646.                     goto    Execute;
  647.                     break;
  648.  
  649.                 default    :
  650.                     break;
  651.                 }
  652.             
  653.             if( parseErr )
  654.                 break;
  655.             }        
  656.  
  657.         lastToken = tokenType;
  658.         }
  659. /*
  660.  *    Start execution of any commands
  661.  */
  662.     if( parseErr )
  663.         {
  664.         procPrintf( ShellWh, ProcID, "%s", string );
  665.         ShellError( parseErr );
  666.         }
  667.     
  668.     if( lastProcSlot != CL_PROCID )
  669.         ProcMgrIdle( ShellWh );
  670.  
  671.     (**ShellWh).entryCnt--;
  672. }
  673.  
  674. /*******************************************************************/
  675. /*
  676.  *    Receive raw input from the command line
  677.  *    Break into lines
  678.  */
  679.  
  680. ShellTextInput( Handle theText, long len, WHandle ShellWh )
  681. {
  682. char    buf[ 256 ], *cp;
  683. long    i = 0, total = 0;
  684. ShellWindRec    **MyShell  = (ShellWindRec **) (**ShellWh).thing;
  685.  
  686.     cp = *theText;
  687.     cp += (**MyShell).promptBase;
  688.     len -= (**MyShell).promptBase;
  689.     
  690.     while( *cp && total < len )
  691.         {
  692.         /* Copy a line */
  693.         i = 0;
  694.         while( total < len )
  695.             {
  696.             if( !(*cp) || (*cp == '\n') || (*cp == '\r') || (i > 250 ))
  697.                 break;
  698.             
  699.             buf[i++] = *cp++;
  700.             total++;
  701.             }
  702.  
  703.         if( *cp == '\n' || *cp == '\r' )
  704.             buf[ i++ ] = '\n';
  705.         buf[ i++ ] = '\0';    /* end of this string */
  706.         CommandString( buf, ShellWh );
  707.         
  708.         if( total >= len || *cp == '\0' )
  709.             break;
  710.         else if( (*cp == '\n') || (*cp == '\r') )
  711.             {
  712.             cp++;
  713.             total++;
  714.             }
  715.         }        
  716. }
  717.  
  718. /*******************************************************************
  719.  *    Init the process manager
  720.  *
  721.  *        The stdIn should be sent to the command line scanner
  722.  *        The stdOut and strErr is sent to the shell
  723.  *
  724.  *******************************************************************/
  725.  
  726. ResetStdIO( WHandle ShellWh )
  727. {
  728. ShellWindRec    **MyShell;
  729.  
  730.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  731.     
  732.     if( (**MyShell).prompt != 0 )
  733.         {
  734.         (**MyShell).prompt = 0;
  735.         CleanShellInput( ShellWh );
  736.         }
  737.  
  738. #ifdef    PROCDEBUG
  739.     printf( "ResetStdIO\n" );
  740. #endif            
  741. /*
  742.  *    Setup standard output
  743.  */    
  744.     (**MyShell).Proc[ STDOUT_PROCID ].CmdProcPtr     = (ProcPtr) StdOutProc;
  745.     (**MyShell).Proc[ STDOUT_PROCID ].ProcActive     = TRUE;
  746. /*
  747.  *    Setup standard error
  748.  */    
  749.     (**MyShell).Proc[ STDERR_PROCID ].CmdProcPtr     = (ProcPtr) StdErrProc;
  750.     (**MyShell).Proc[ STDERR_PROCID ].ProcActive     = TRUE;
  751.     
  752. /*
  753.  *    Setup standard input
  754.  */    
  755.     (**MyShell).Proc[ STDIN_PROCID ].CmdProcPtr     = (ProcPtr) StdInProc;
  756.     (**MyShell).Proc[ STDIN_PROCID ].ProcActive     = TRUE;
  757.     (**MyShell).Proc[ STDIN_PROCID ].StdOutProcID     = CL_PROCID;
  758.     
  759. /*
  760.  *    Setup shell scanner
  761.  */    
  762.     (**MyShell).Proc[ CL_PROCID ].CmdProcPtr     = (ProcPtr) CLScanner;
  763.     (**MyShell).Proc[ CL_PROCID ].ProcActive     = TRUE;
  764. }
  765.  
  766. /*******************************************************************/
  767.  
  768. InitProcMgr( WHandle ShellWh )
  769. {
  770. int    p;
  771. ShellWindRec    **MyShell;
  772.  
  773.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  774.     (**MyShell).ShellWh = ShellWh;
  775.  
  776.     for( p = 0; p < MAX_PROCS; p++ )    /* Clean records */
  777.         {
  778.         (**MyShell).Proc[ p ].ProcActive     = FALSE;
  779.         (**MyShell).Proc[ p ].ProcID         = p;
  780.         
  781.         (**MyShell).Proc[ p ].fileRefNum     = 0;
  782.         (**MyShell).Proc[ p ].CmdProcPtr     = ShellOutProc;
  783.                 
  784.         (**MyShell).Proc[ p ].argc             = UNKNOWN;
  785.         (**MyShell).Proc[ p ].StdOutProcID     = STDOUT_PROCID;
  786.         (**MyShell).Proc[ p ].StdErrProcID     = STDERR_PROCID;
  787.         (**MyShell).Proc[ p ].locStorage     = NULL;
  788.         (**MyShell).Proc[ p ].flags             = 0;
  789.         }
  790.         
  791.     (**MyShell).numProcs = 4;
  792.     ResetStdIO( ShellWh );
  793. }
  794.  
  795. /*******************************************************************
  796.  *    This function is called by the Idle method of a shell
  797.  *    It monitors all procs and send messages between them if needed.
  798.  *******************************************************************/
  799.  
  800. ProcMgrIdle( WHandle ShellWh )
  801. {
  802. int                i, start = 0;
  803. ProcPtr            p;
  804. ShellWindRec    **MyShell = (ShellWindRec **) (**ShellWh).thing;
  805.  
  806.     for( i = start; i < MAX_PROCS; i++ )
  807.         if( (**MyShell).Proc[ i ].ProcActive )
  808.             {
  809.             p = (**MyShell).Proc[ i ].CmdProcPtr;
  810.         
  811.             if( p )
  812.                 (*p)( PROC_STDIN, ShellWh, i, NULL );
  813.             }
  814. }